#include "Node.h"
#include <cstdio>

#include <math.h>

using namespace std;

Node::Node(Image* image) {
    setFather(NULL);
    this->setLeaf(image);
}

Node::Node(Node* left, Orientation orientation, Node* right) {
    setFather(NULL);
    this->setBissection(left, orientation, right);
}

Node::Node(Node* node) {
    setFather(node->getFather());
    if(node->isLeaf()) {
        setLeaf(new Image(node->getImage()));
    } else {
        setBissection(new Node(node->getLeft()), node->getOrientation(), new Node(node->getRight()));
    }
}

void Node::setBissection(Node* left, Orientation orientation, Node* right) {
    this->setLeft(left);
    this->setRight(right);
    this->orientation = orientation;
    this->type = BISS;
}

void Node::setLeaf(Image* imagem) {
    this->image = imagem;
    this->type = LEAF;
}

Image* Node::getImage() {
    return this->image;
}

Node* Node::getLeft() {
    return this->left;
}

Node* Node::getRight() {
    return this->right;
}

Orientation Node::getOrientation() {
    return this->orientation;
}

Type Node::getType() {
    return this->type;
}

int Node::getId() {
    return this->id;
}

void Node::setId(int id) {
    this->id = id;
}

void Node::enumerate() {
    
}

double Node::sumImageAreas() {
    return isLeaf() ? getImage()->getArea() : (getLeft()->sumImageAreas() + getRight()->sumImageAreas());
}

double Node::sumPriorities() {
    return isLeaf() ? getImage()->getRelativeArea() : (getLeft()->sumPriorities() + getRight()->sumPriorities());
}

void Node::setLeft(Node* left) {
    this->left = left;
    left->setFather(this);
}

void Node::setRight(Node* right) {
    this->right = right;
    right->setFather(this);
}

Node* Node::getFather() {
    return this->father;
}

void Node::setFather(Node* father) {
    this->father = father;
}

/*void Node::copy(Node* raiz) {
    if(raiz) {
        if(raiz->getType() == BISS) {
            Node* left = new Node(raiz->getLeft()->getType());
            Node* right = new Node(raiz->getRight()->getType());
            left->copy(raiz->getLeft());
            right->copy(raiz->getRight());
            
            this->setBissection(left, raiz->getOrientation(), right);
        } else {
            Image* img = raiz->getImage();
            this->setLeaf(new Image(img->getWidth(), img->getHeight(), img->getPriority()));
        }
    }
}*/

double max(double a, double b) {
    return a > b ? a : b;
}

double Node::getHeight(int alpha, int beta) {
    if(this->getType() == BISS) {
        if(this->getOrientation() == HORIZONTAL) {
            return this->getLeft()->getHeight(alpha, beta) + this->getRight()->getHeight(alpha, beta) + alpha;
        } else {
            return max(this->getLeft()->getHeight(alpha, beta), this->getRight()->getHeight(alpha, beta));
        }
    } else {
        return this->getImage()->getHeight() + 2.0*beta;
    }
}

double Node::getWidth(int alpha, int beta) {
    if(this->getType() == BISS) {
        if(this->getOrientation() == HORIZONTAL) {
            return max(this->getLeft()->getWidth(alpha, beta), this->getRight()->getWidth(alpha, beta));
        } else {
            return this->getLeft()->getWidth(alpha, beta) + this->getRight()->getWidth(alpha, beta) + alpha;
        }
    } else {
        return this->getImage()->getWidth() + 2.0*beta;
    }
}

double Node::getArea(int alpha, int beta) {
    return getHeight(alpha, beta) * getWidth(alpha, beta);
}

bool Node::isLeaf() {
    return this->getType() == LEAF;
}